﻿using AOT;
using BulletSharp;
using DMatrix = BulletSharp.Math.Matrix;
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
using UnityEngine;

namespace ETModel {


    public delegate void BulletCollisionObjectWorldTransformChanged(ref Vector3 newPos, ref Quaternion newRotation);

    public delegate void BulletCollisionObjectWorldTransformChangedTest(ref DMatrix worldTrans);

    /// <summary>
    /// 物理对象的运动状态同步类,使用OnWorldTransformChanged事件
    /// </summary>
    public class BulletCollisionObjectMotionState : MotionState {

        /// <summary>
        /// 由物理世界里驱动矩阵变化后触发
        /// </summary>
        public event BulletCollisionObjectWorldTransformChanged OnWorldTransformChanged;

        protected DMatrix _worldTrans = DMatrix.Identity;
        protected Vector3 _outPosition = Vector3.zero;
        protected Quaternion _outRotation = Quaternion.identity;

        /// <summary>
        /// 更新状态中保存的世界矩阵和输出的参数,返回是否有变更
        /// </summary>
        /// <param name="newMatrix"></param>
        /// <returns></returns>
        protected bool UpdateWorldTransAndOutVal(ref DMatrix newMatrix) {
            var change = (newMatrix != _worldTrans);
            if (change) {
                _worldTrans = newMatrix;
                _outPosition = _worldTrans.GetU3DVector3();
                _outRotation = _worldTrans.GetU3DRotation();
                //_outRotation.Normalize();
            }
            return change;
        }

        public BulletCollisionObjectMotionState() : base() {
        }

        public BulletCollisionObjectMotionState(DMatrix startTrans) : base() {
            if (UpdateWorldTransAndOutVal(ref startTrans)) {
                btMotionState_setWorldTransform(_native, ref _worldTrans);
            }
        }

        /// <summary>
        /// [仅提供物理引擎调用]
        /// </summary>
        /// <param name="worldTrans"></param>
        public override void GetWorldTransform(out DMatrix worldTrans) {
            worldTrans = _worldTrans;
        }
        /// <summary>
        /// [仅提供物理引擎调用]
        /// </summary>
        /// <param name="worldTrans"></param>
        public override void SetWorldTransform(ref DMatrix worldTrans) {
            if (UpdateWorldTransAndOutVal(ref worldTrans)) {
                OnWorldTransformChanged?.Invoke(ref _outPosition, ref _outRotation);
            }
        }


        /// <summary>
        /// 获取对象在物理世界中的矩阵数值
        /// </summary>
        /// <returns></returns>
        public DMatrix GetWorldTrans() {
            return _worldTrans;
        }
        /// <summary>
        /// 设置对象在物理世界中的矩阵数值,会触发事件
        /// </summary>
        /// <param name="worldTrans"></param>
        public void SetWorldTrans(ref DMatrix worldTrans) {
            if (UpdateWorldTransAndOutVal(ref worldTrans)) {
                btMotionState_setWorldTransform(_native, ref _worldTrans);
            }
        }


        [DllImport(Native.Dll, CallingConvention = Native.Conv), SuppressUnmanagedCodeSecurity]
        static extern void btMotionState_getWorldTransform(IntPtr obj, [Out] out DMatrix worldTrans);
        [DllImport(Native.Dll, CallingConvention = Native.Conv), SuppressUnmanagedCodeSecurity]
        static extern void btMotionState_setWorldTransform(IntPtr obj, [In] ref DMatrix worldTrans);

    }
}
